package org.firebug.generator.micro.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * twitter snow flake generator
 * 从左向右
 * 63位: 置0
 * 62-22位: timestamp 时间戳
 * 22-12位: worker   机器号
 * 11-0位: sequence 序列号
 * 使用注意：
 * 本机时间不能调整
 */
@Service
public class SnowflakeService {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private long timestamp = System.currentTimeMillis();
    @Value("${generator.snowflake.worker}")
    private long worker = 0L;
    private long sequence = 0L;

    public List<Long> get(int count) {
        List<Long> keys = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            keys.add(get());
        }
        return keys;
    }

    public synchronized long get() {
        long now = System.currentTimeMillis();
        if (now > timestamp) {
            timestamp = now;
            sequence = 0L;
        } else if (now == timestamp) {
            sequence++;
            if (sequence > 0xFFFL) {
                while (System.currentTimeMillis() <= timestamp) {}
                timestamp = System.currentTimeMillis();
                sequence = 0L;
            }
        } else if (now < timestamp) {
            logger.warn("Clock is moving backwards. Rejecting requests till {}.", timestamp);
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to create for %d milliseconds", timestamp - now));
        }
        return timestamp << 22 | worker << 12 | sequence;
    }
}